package com.itheima.health.security;

import com.alibaba.fastjson.JSON;
import com.itheima.health.dao.PermissionDao;
import com.itheima.health.dao.RoleDao;
import com.itheima.health.dao.UserDao;
import com.itheima.health.entity.Result;
import com.itheima.health.pojo.Permission;
import com.itheima.health.pojo.Role;
import com.itheima.health.pojo.User;
import com.itheima.health.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;


@Slf4j
@WebFilter(urlPatterns = "/*")
public class HealthSecurityFilter implements Filter {

	@Autowired
	private UserService userService;

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
						 FilterChain filterChain) throws IOException, ServletException {
		//拦截所有请求
		HttpServletRequest request = (HttpServletRequest) servletRequest;
		HttpServletResponse response = (HttpServletResponse) servletResponse;
		// 1.获取URI
		String uri = request.getRequestURI();
		log.info("[权限检查过滤器...],当前uri:{}", uri);

//			filterChain.doFilter(request,response);
		boolean noNeedLogin = checkURI(uri);
		if (noNeedLogin) {
			log.info("该路径是白名单,可以直接放行,无需登录访问");
			//返回结果是true 说明不需要登录 直接可以访问 不用拦截
			filterChain.doFilter(request, response);
			return;
		}
		User user = (User) request.getSession().getAttribute("user");

		//判断用户是否为空
		if (user != null) {
			//用户不为空说明用户已经登录了
			//创建一个方法用来判断请求路径和map中的键对应的情况下  user权限表中的权限关键字和map中的值是否对应
			Boolean loginAuthURI = checkLoginAuthURI(uri, user);

			if (loginAuthURI) {
				//返回的是true 说明是对应的  即可访问
				filterChain.doFilter(request, response);


			} else {
				//返回结果为false 说明没有权限
				response.setContentType("application/json;charset=utf-8");
				Result result = new Result(false, "没有访问权限");
				String s = JSON.toJSONString(result);
				response.getWriter().write(s);
			}


		} else {
			//用户为空说明还没有登录  返回重新登陆
			response.setContentType("application/json;charset=utf-8");
			Result result = new Result(false, "重新登陆");
			String s = JSON.toJSONString(result);
			response.getWriter().write(s);
		}


	}

	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private PermissionDao permissionDao;

	private Boolean checkLoginAuthURI(String uri, User user) {
		AntPathMatcher matcher = new AntPathMatcher();

		//根据路径具备的权限 把路劲里的关键字拿出来
		String currKeyUrl = null;//用它来接收 匹配出来的 路径规则

		Set<String> keySet = initAutlUrlMap.keySet();
		for (String keyUri : keySet) {
			if (matcher.match(keyUri, uri)) {
				currKeyUrl = keyUri;
			}
		}

		if (currKeyUrl == null) {
			//不需要访问权限 可以直接访问
			log.info("当前访问路径,不需要权限校验,谁都有权限...");
			return true;
		}
		String username = user.getUsername();
		User user1 = userDao.selectByUsername(username);
		List<Role> roles = roleDao.selectByUserId(user1.getId());
		List<Permission> permissionList = new ArrayList<>();
		for (Role role : roles) {
			List<Permission> permissions = permissionDao.selectById(role.getId());
			for (Permission permission : permissions) {
				permissionList.add(permission);
			}
		}


		//如果到了这里就说明 访问的这个路径需要 授权 取出关键字
		String authKeyword = initAutlUrlMap.get(currKeyUrl);
		log.info("该路径需要权限访问,且访问权限关键字是:" + authKeyword);

		//查询到用户的所有权限  拿出用户权限的关键字
		//进行对比
		for (Permission persion : permissionList) {
			String name = persion.getKeyword();
			if (authKeyword.equals(name)) {
				log.info("当前用户权限匹配上了,允许访问");
				return true;
			}
		}

		return false;

	}


	//判断是否在白名单里的方法
	private boolean checkURI(String reqUri) {
		//  判断一个 这个 reqUri 是不是白名单数据
		//   路径匹配器
		AntPathMatcher pathMatcher = new AntPathMatcher();
		//遍历数组
		// url 白名单规则    reqUri 请求的路径
		for (String url : auths) {
			if (pathMatcher.match(url, reqUri)) {
				log.info("[权限过滤器,匹配是白名单:uri:{}]", reqUri);
				return true;
			}
		}

		return false;//需要登录访问
	}

	//白名单 不需要登录就可以访问的
	private String[] auths = new String[]{
			"/user/login",
			"/user/logout",
			"/common/**",
			"/mobile/**" //移动端无需登录
	};


	//创建一个map集合 用来存放对应的权限
	//键 访问的路径
	//值 查询用户表查出来的路径关键字
	private HashMap<String, String> initAutlUrlMap = new HashMap<>();

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		//权限初始化
		initAutlUrlMap();
	}


	private void initAutlUrlMap() {
		initAutlUrlMap.put("/checkgroup/add", "CHECKGROUP_ADD");
		initAutlUrlMap.put("/checkgroup/deleteCheckGroupitemById", "CHECKGROUP_DELETE");
		initAutlUrlMap.put("/checkgroup/edit", "CHECKGROUP_EDIT");
		initAutlUrlMap.put("/checkgroup/findCheckItemIdsByCheckGroupId", "CHECKGROUP_EDIT");
		initAutlUrlMap.put("/checkgroup/findById", "CHECKGROUP_EDIT");
		initAutlUrlMap.put("/checkgroup/findPage", "CHECKGROUP_QUERY");
		initAutlUrlMap.put("/checkitem/add", "CHECKITEM_ADD");
		initAutlUrlMap.put("/checkitem/delete", "CHECKITEM_DELETE");
		initAutlUrlMap.put("/checkitem/edit", "CHECKITEM_EDIT");
		initAutlUrlMap.put("/checkitem/findById", "CHECKITEM_EDIT");
		initAutlUrlMap.put("/checkitem/findPage", "CHECKITEM_QUERY");
		initAutlUrlMap.put("/setmeal/add", "SETMEAL_ADD");
		initAutlUrlMap.put("/setmeal/delete", "SETMEAL_DELETE");
		initAutlUrlMap.put("/setmeal/edit", "SETMEAL_EDIT");
		initAutlUrlMap.put("/setmeal/findPage", "SETMEAL_QUERY");
//		initAutlUrlMap.put("/","MENU_ADD");
//		initAutlUrlMap.put("/","MENU_DELETE");
//		initAutlUrlMap.put("/","MENU_EDIT");
//		initAutlUrlMap.put("/","MENU_QUERY");
//		initAutlUrlMap.put("/","ORDERSETTING");
		initAutlUrlMap.put("/report/**", "REPORT_VIEW");
//		initAutlUrlMap.put("/","ROLE_ADD");
//		initAutlUrlMap.put("/","ROLE_DELETE");
//		initAutlUrlMap.put("/","ROLE_EDIT");
//		initAutlUrlMap.put("/","ROLE_QUERY");
//		initAutlUrlMap.put("/","USER_ADD");
//		initAutlUrlMap.put("/","USER_DELETE");
//		initAutlUrlMap.put("/","USER_EDIT");
//		initAutlUrlMap.put("/","USER_QUERY");
		;
	}
}


